package com.mokairui.example;

/**
 * @Program: java-basic-summary
 * @Description:
 * @Author Mokairui
 * @Date 2021/5/23 17:40
 */
public class TestDemo {
    /**
     * 字符串有家养和野生两种，家养的意思就是常规的字面量定义，放在StringTable中
     * 有去重的效果，StringTable可以简单的理解为一个hash的map表每次都从这个map中去查询是否有
     * 已经相同的字符串，而野生就是通过new, byte[], int[], char[], + 对象等这些方式，
     * 这些方式是没有去重的
     */
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "abc";
        String s3 = new String(new char[]{'a', 'b', 'c'});
        String s4 = "a" + "bc";
        String x = "a";
        String s5 = x + "bc";

        System.out.println(s1 == s2); // true
        System.out.println(s1 == s3); // false
        System.out.println(s1 == s4); // true
        System.out.println(s1 == s5); // false
        
        /*
                 在Java中，字符串对象是通过String类的intern()方法进行存储的。当通过字面量定义一个字符串时，如"abc"，Java会首先检查字符串常量池，
             如果字符串常量池中已经存在该字符串，则直接返回常量池的引用；如果字符串常量池中不存在该字符串，则会在常量池中创建一个新的字符串对象，并返回该对象的引用。
             
                 对于s1 = "abc"，由于"abc"是一个字面量字符串，Java会在常量池中创建一个字符串对象，然后将s1指向该对象。
                 对于s4 = "a" + "bc"，由于"a"和"bc"都是字面量字符串，编译器会在编译期间直接将"a"和"bc"拼接成"abc"，然后创建一个新的字符串对象，并返回该对象的引用。
             因此，s4也指向常量池中的同一个对象。而对于s5 = x + "bc"，由于x是一个变量，编译器无法在编译期间确定x的值，所以会将字符串拼接操作推迟到运行时。
             在运行时，会先创建一个新的StringBuilder对象，将x的值和"bc"拼接，然后调用toString()方法将结果转换为字符串。
             由于StringBuilder生成的新的String对象在堆上创建，而不是在常量池中，所以s5指向的是堆上的新对象。
             因此，尽管s4和s5的值是相同的，但s1和s4都指向了常量池中的同一个对象，所以s1 == s4为true；
             而s1和s5分别指向常量池和堆上的不同对象，所以s1 == s5为false。
         */
        
    }
}
